package com.ruoyi.web.controller.bike;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.opencsv.CSVReader;
import com.opencsv.exceptions.CsvException;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysOrder;
import com.ruoyi.common.dto.BikeDTO;
import com.ruoyi.system.service.ISysOrderService;
import com.ruoyi.web.controller.openfeign.FileClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/api/bike")
public class BikeController {

    @Autowired
    private ISysOrderService sysOrderService;

    @Autowired
    private FileClient fileClient;

    @Value("${file.base-http-url}")
    private String baseHttpUrl;

    private ThreadPoolExecutor executorService;

    @PostConstruct
    public void init() {
        executorService = new ThreadPoolExecutor(
                10, // 核心线程数
                20, // 最大线程数
                60L, // 线程空闲时间
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(1000), // 任务队列
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.CallerRunsPolicy()
        );
    }

    @PreDestroy
    public void destroy() {
        executorService.shutdown();
    }




   // @PostMapping("/order/process")
    @Transactional
    public AjaxResult writeCsv(@RequestBody List<BikeDTO> requestDataList) {
        if (requestDataList == null || requestDataList.isEmpty()) {
            log.error("请求数据为空，无法生成 CSV 文件");
            return AjaxResult.error(400, "请求数据为空，无法生成 CSV 文件");
        }

        int batchSize = 20;
        List<List<BikeDTO>> batches = partitionList(requestDataList, batchSize);
        List<HashMap<String, Object>> finalResultList = Collections.synchronizedList(new ArrayList<>());

        for (List<BikeDTO> batch : batches) {
            String timestamp = String.valueOf(System.currentTimeMillis());
            String randomNum = generateRandomNumber(10);
            String fileName = timestamp + "_" + randomNum + ".csv";
            String filePath = "/data/" + fileName;

            List<SysOrder> orderList = Collections.synchronizedList(new ArrayList<>());

            CompletableFuture<Void> csvFuture = CompletableFuture.runAsync(() -> {
                try (BufferedWriter fileWriter = new BufferedWriter(new FileWriter(filePath))) {
                    fileWriter.write("charging_station_id charging_powers_str");
                    fileWriter.newLine();

                    batch.parallelStream().forEach(requestData -> {
                        List<Integer> powerList = requestData.getPowerList();
                        if (powerList.isEmpty()) {
                            return;
                        }

                        StringBuilder rowBuilder = new StringBuilder();
                        rowBuilder.append(requestData.getRecordNo()).append(" ").append(powerList.get(0));
                        for (int i = 1; i < powerList.size(); i++) {
                            rowBuilder.append(",").append(powerList.get(i));
                        }

                        synchronized (this) {
                            try {
                                fileWriter.write(rowBuilder.toString());
                                fileWriter.newLine();
                            } catch (IOException e) {
                                log.error("写入 CSV 文件失败", e);
                            }
                        }

                        SysOrder sysOrder = new SysOrder();
                        sysOrder.setRecordNo(requestData.getRecordNo());
                        sysOrder.setPowerList(powerList.toString());
                        sysOrder.setCreateTime(new Date());
                        sysOrder.setFileUrl(baseHttpUrl + fileName);
                        sysOrder.setMarkType(requestData.getMarkType());
                        orderList.add(sysOrder);
                    });
                } catch (IOException e) {
                    log.error("生成 CSV 文件时发生 IO 错误", e);
                }
            }, executorService);

            csvFuture.join();

            if (!orderList.isEmpty()) {
                CompletableFuture.runAsync(() -> sysOrderService.batchSave(orderList), executorService).join();
            }

            Map<String, String> request = new HashMap<>();
            request.put("file_url", baseHttpUrl + fileName);
            Map<String, Object> fileInfo = fileClient.getFile(request);
            if (fileInfo == null || !fileInfo.containsKey("result_file_url")) {
                log.error("文件信息为空，无法获取预测结果文件");
                return AjaxResult.error(500, "无法获取预测结果文件");
            }

            String localFilePath = "/data/测试_带预测结果.csv";
            List<List<String>> csvData = readCsvFile(localFilePath);

            File file = new File(filePath);
            if (file.exists() && file.delete()) {
                log.info("成功删除 CSV 文件: {}", filePath);
            } else {
                log.warn("删除 CSV 文件失败: {}", filePath);
            }

            List<SysOrder> updateList = Collections.synchronizedList(new ArrayList<>());
            List<HashMap<String, Object>> resultList = Collections.synchronizedList(new ArrayList<>());

            csvData.stream().skip(1).parallel().forEach(row -> {
                String rawRecordNo = row.get(0);
                String rawResult = row.get(row.size() - 1);

                try {
                    String recordNo = rawRecordNo.split(" ")[0];
                    String result = rawResult.split(" ")[rawResult.split(" ").length - 1];

                    List<SysOrder> sysOrders = sysOrderService.list(new QueryWrapper<SysOrder>().eq("record_no", recordNo));
                    sysOrders.forEach(sysOrder -> {
                        sysOrder.setResult(Integer.parseInt(result));
                        updateList.add(sysOrder);
                    });

                    HashMap<String, Object> resultData = new HashMap<>();
                    resultData.put("recordNo", recordNo);
                    resultData.put("result", Integer.parseInt(result));
                    resultList.add(resultData);
                } catch (NumberFormatException e) {
                    log.error("解析文件时发生错误", e);
                }
            });

            if (!updateList.isEmpty()) {
                CompletableFuture.runAsync(() -> sysOrderService.updateBatchById(updateList), executorService).join();
            }

            finalResultList.addAll(resultList);
        }

        return AjaxResult.success(finalResultList);
    }



    // 方法用于将请求数据分割为多个批次
    private List<List<BikeDTO>> partitionList(List<BikeDTO> list, int batchSize) {
        List<List<BikeDTO>> batches = new ArrayList<>();
        for (int i = 0; i < list.size(); i += batchSize) {
            int end = Math.min(i + batchSize, list.size());
            batches.add(list.subList(i, end));
        }
        return batches;
    }


    private List<List<String>> readCsvFile(String filePath) {
        List<List<String>> records = new ArrayList<>();
        try (BufferedReader reader = Files.newBufferedReader(Paths.get(filePath));
             CSVReader csvReader = new CSVReader(reader)) {
            records = csvReader.readAll().stream().map(Arrays::asList).collect(Collectors.toList());
        } catch (IOException | CsvException e) {
            log.error("读取 CSV 文件失败，路径：{}", filePath, e);
        }
        return records;
    }

    private String generateRandomNumber(int length) {
        Random random = new Random();
        return random.ints(0, 10).limit(length).mapToObj(String::valueOf).collect(Collectors.joining());
    }
}
